"""
@Author  : 康帅
@Time    : 2021/5/25 14:18
@Function: Python redis String使用
"""

# 安装
# sudo pip3 install redis

import redis
import time

#  使用连接池连接，避免每次建立、释放连接的开销
# redis 取出的结果默认是字节，我们可以设定 decode_responses=True 改成字符串
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)

"""
基本命令 String
set(name, value, ex=None, px=None, nx=False, xx=False)
ex - 过期时间（秒）
px - 过期时间（毫秒）
nx - 如果设置为True，则只有name不存在时，当前set操作才执行
xx - 如果设置为True，则只有name存在时，当前set操作才执行
"""

# ex - 过期时间（秒） 这里过期时间是3秒，3秒后p，键food的值就变成None
r.set('food', 'mutton', ex=3)  # key是"food" value是"mutton" 将键值对存入redis缓存
print(r.get('food'))  # mutton 取出键food对应的值

# px - 过期时间（豪秒） 这里过期时间是3豪秒，3毫秒后，键foo的值就变成None
r.set('food', 'beef', px=3)
print(r.get('food'))

# nx - 如果设置为True，则只有name不存在时，当前set操作才执行 （新建）
print(r.set('fruit', 'watermelon', nx=True))  # True--不存在
# 如果键fruit不存在，那么输出是True；如果键fruit已经存在，输出是None

# xx - 如果设置为True，则只有name存在时，当前set操作才执行 （修改）
print((r.set('fruit', 'watermelon', xx=True)))  # True--已经存在
# 如果键fruit已经存在，那么输出是True；如果键fruit不存在，输出是None

# setnx(name, value) 设置值，只有name不存在时，执行设置操作（添加）
print(r.setnx('fruit1', 'banana'))  # fruit1不存在，输出为True

# setex(name, time, value)time - 过期时间（数字秒 或 timedelta对象）
r.setex("fruit2", 5, "orange")
time.sleep(5)
print(r.get('fruit2'))  # 5秒后，取值就从orange变成None

# psetex(name, time_ms, value) time_ms - 过期时间（数字毫秒 或 timedelta对象）
r.psetex("fruit3", 5000, "apple")
time.sleep(5)
print(r.get('fruit3'))  # 5000毫秒后，取值就从apple变成None

# mset(*args, **kwargs) 批量设置值
r.mget({'k1': 'v1', 'k2': 'v2'})
print(r.mget("k1", "k2"))  # 一次取出多个键对应的值
print(r.mget("k1"))  # 一次取出一个键对应的值

# mget(keys, *args) 批量获取
print(r.mget('k1', 'k2'))
print(r.mget(['k1', 'k2']))
print(r.mget("fruit", "fruit1", "fruit2", "k1", "k2"))  # 将目前redis缓存中的键对应的值批量取出来

# getset(name, value) 设置新值并获取原来的值
print(r.getset("food", "barbecue"))  # 设置的新值是barbecue 设置前的值是beef

# getrange(key, start, end) 获取子序列（根据字节获取，非字符）
# name - Redis 的 name
# start - 起始位置（字节）
# end - 结束位置（字节）
r.set("cn_name", "君惜大大")  # 汉字
print(r.getrange("cn_name", 0, 2))  # 取索引号是0-2 前3位的字节 君 切片操作 （一个汉字3个字节 1个字母一个字节 每个字节8bit）
print(r.getrange("cn_name", 0, -1))  # 取所有的字节 君惜大大 切片操作
r.set("en_name", "junxi")  # 字母
print(r.getrange("en_name", 0, 2))  # 取索引号是0-2 前3位的字节 jun 切片操作 （一个汉字3个字节 1个字母一个字节 每个字节8bit）
print(r.getrange("en_name", 0, -1))  # 取所有的字节 junxi 切片操作

# setrange(name, offset, value) 修改字符串内容，从指定字符串索引开始向后替换（新值太长时，则向后添加）
# offset - 字符串的索引，字节（一个汉字三个字节）
# value - 要设置的值
r.setrange("en_name", 1, "ccc")
print(r.get("en_name"))  # jccci 原始值是junxi 从索引号是1开始替换成ccc 变成 jccci

# bitop(operation, dest, *keys) 获取多个值，并将值做位运算，将最后的结果保存至新的name对应的值
# operation - AND（并） 、 OR（或） 、 NOT（非） 、 XOR（异或）
# dest - 新的Redis的name
# *keys - 要查找的Redis的name
r.set("foo", "1")  # 0110001
r.set("foo1", "2")  # 0110010
print(r.mget("foo", "foo1"))  # ['goo1', 'baaanew']
print(r.bitop("AND", "new", "foo", "foo1"))  # "new" 0 0110000
print(r.mget("foo", "foo1", "new"))

# strlen(name) 返回name对应值的字节长度（一个汉字3个字节）
print(r.strlen("foo"))  # 4 'goo1'的长度是4

# incr(self, name, amount=1) 自增 name 对应的值，当 name 不存在时，则创建 name＝amount，否则，则自增
# name - Redis的name
# amount - 自增数（必须是整数）
r.set("foo", 123)
print(r.mget("foo", "foo1", "foo2", "k1", "k2"))
r.incr("foo", amount=1)
print(r.mget("foo", "foo1", "foo2", "k1", "k2"))

# incrbyfloat(self, name, amount=1.0) 自增 name对应的值，当name不存在时，则创建name＝amount，否则，则自增
# name - Redis的name
# amount - 自增数（浮点型）
r.set("foo1", "123.0")
r.set("foo2", "221.0")
print(r.mget("foo1", "foo2"))
r.incrbyfloat("foo1", amount=2.0)
r.incrbyfloat("foo2", amount=3.0)
print(r.mget("foo1", "foo2"))

# decr(self, name, amount=1) 自减 name 对应的值，当 name 不存在时，则创建 name＝amount，否则，则自减
# name - Redis的name
# amount - 自减数（整数)
r.decr("foo4", amount=3)  # 递减3
r.decr("foo1", amount=1)  # 递减1
print(r.mget("foo1", "foo4"))

# append(key, value) 在redis name对应的值后面追加内容
# key - redis的name
# value - 要追加的字符串
r.append("name", "haha")    # 在name对应的值junxi后面追加字符串haha
print(r.mget("name"))
